module how.poker {
    /**
     * 全局模块-牌型判断逻辑
     * @author 袁浩
     *
     */
    export class CardLogic_DDZ3 {
        /** 花色掩码 **/
        private static MASK_COLOR: number = 0xF0;
        /** 数值掩码 **/
        private static MASK_VALUE: number = 0x0F;
        /** 扑克数据 **/
        public static cardDataArray: number[] =
        [
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, //方块 A - K
            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, //梅花 A - K
            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, //红桃 A - K
            0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, //黑桃 A - K
            0x4E, 0X4F//大小王
        ];
        /** 获取数值 **/
        public static getCardValue(cardData: number): number {
            return (cardData & this.MASK_VALUE);
        }
        /** 获取花色 **/
        public static getCardColor(cardData: number): number {
            return (cardData & this.MASK_COLOR) / 16;
        }
        /** 根据值获取牌数据 **/
        public static getCardByValue(cardData: number[], cardValue: number): number {
            for (var i: number = 0; i < cardData.length; i++) {
                if (this.getCardValue(cardData[i]) == cardValue) {
                    return cardData[i];
                }
            }
            return 0;
        }
        public static testData: number[];
        /** 根据牌值排序，从大到小，2最大 **/
        public static sortByCardData(cardData: number[]): void {
            var isSame = true;
            for (var i = 0; i < cardData.length - 1; i++) {
                if (cardData[i] != cardData[i + 1]) {
                    isSame = false;
                    break;
                }
            }
            if (isSame) {//如果都是一样的就不需要排序了
                return;
            }
            this.testData = cardData;
            var self = CardLogic_DDZ3;
            cardData.sort((left: number, right: number) => {
                var leftValue: number = self.getCardValue(left);
                var rightValue: number = self.getCardValue(right);
                leftValue = leftValue <= 2 ? 13 + leftValue / 10 : leftValue;
                rightValue = rightValue <= 2 ? 13 + rightValue / 10 : rightValue;
                if (leftValue > rightValue) {
                    return -1;
                }
                else if (leftValue < rightValue) {
                    return 1;
                }
                else {
                    var leftColor: number = self.getCardColor(left);
                    var rightColor: number = self.getCardColor(right);
                    if (leftColor > rightColor) {
                        return 1;
                    }
                    else if (leftColor < rightColor) {
                        return -1;
                    }
                    return 0;
                }
            });
        }
        /** 根据花色排序，从大到小 **/
        private static sortByColor(cardData: number[]): void {
            var self = CardLogic_DDZ3;
            cardData.sort((left, right) => {
                if (self.getCardColor(left) > self.getCardColor(right)) {
                    return -1;
                }
                else if (self.getCardColor(left) < self.getCardColor(right)) {
                    return 1;
                }
                else {
                    return 0;
                }
            });
        }
        public static getString(cardData: number[]): string[] {
            var result: string[] = [];
            for (var i = 0; i < cardData.length; i++) {
                result.push("0x" + cardData[i].toString(16));
            }
            return result;
        }
        /**
         * 查找单张
         */
        public static findSingle(cardData: number[], minCard: number = 0x00): number[] {
            var result: number[] = [];
            this.sortByCardData(cardData);
            for (var i: number = 0; i < cardData.length; i++) {
                if (this.getCardValue(cardData[i]) != this.getCardValue(cardData[i + 1]) || i == cardData.length - 1) {//和后者不一样
                    if (i == 0 || this.getCardValue(cardData[i]) != this.getCardValue(cardData[i - 1])) {//和前者不一样
                        if (this.compare(cardData[i], minCard)) {
                            result.push(cardData[i]);
                        }
                    }
                }
                else {
                    i++;
                }
            }
            if (result.length) {//如果有单张，则只返回单张
                return result;
            }
            else {//否则返回全部
                for (var i: number = 0; i < cardData.length; i++) {
                    if (this.compare(cardData[i], minCard)) {
                        result.push(cardData[i]);
                    }
                }
                return this.removeSameValue2(result);
            }
        }
        /**
         * 查找顺子
         * @param cardData 自己的牌数据
         * @param length 顺子长度
         */
        public static findSingleLine(cardData: number[], linelength: number = 5, minCard: number = 0x00, minLength: number = 5): Array<number[]> {
            var result: Array<number[]> = [];
            if (linelength < minLength) {
                return result;
            }
            this.sortByCardData(cardData);
            var lineData: number[] = [];
            for (var i: number = 0; i < cardData.length; i++) {
                lineData.push(cardData[i]);
                for (var j: number = i + 1; j < cardData.length; j++) {
                    if (((this.getCardValue(cardData[i]) == 1 ? 14 : this.getCardValue(cardData[i])) - this.getCardValue(cardData[j])) == lineData.length && //数字之间小于等于4
                        this.getCardValue(cardData[i]) != this.getCardValue(cardData[j]) && //前后不相等
                        this.getCardValue(cardData[i]) != 2 && //不等于2
                        this.getCardValue(cardData[i]) < 0xe && //不是王
                        this.compare(cardData[i], minCard)) {//大于最小值
                        lineData.push(cardData[j]);
                        if (lineData.length == linelength) {//5个已满
                            result.push(lineData);
                            break;
                        }
                    }
                    else {
                        continue;
                    }
                }
                if (this.getCardValue(cardData[i]) == 1) {
                    lineData = [];
                    lineData.push(cardData[i]);
                    for (var j: number = i + 1; j < cardData.length; j++) {
                        var isPush = 1 - this.getCardValue(cardData[j]) == lineData.length - linelength && //数字之间小于等于-4
                            this.getCardValue(cardData[i]) != this.getCardValue(cardData[j]);
                        if (isPush) {
                            lineData.push(cardData[j]);
                            if (lineData.length == linelength) {//5个已满
                                result.push(lineData);
                                break;
                            }
                        }
                        else {
                            continue;
                        }
                    }
                }
                lineData = [];
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找炸弹
         */
        public static findBoom(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            for (var i: number = 0; i < cardData.length; i++) {
                if (i + 3 < cardData.length)//如果剩余有4张
                {
                    if (this.getCardValue(cardData[i]) == this.getCardValue(cardData[i + 1])
                        && this.getCardValue(cardData[i + 1]) == this.getCardValue(cardData[i + 2])
                        && this.getCardValue(cardData[i + 2]) == this.getCardValue(cardData[i + 3])
                        && this.compare(cardData[i], minCard))//4张全部相等
                    {
                        var fourData: number[] = [cardData[i], cardData[i + 1], cardData[i + 2], cardData[i + 3]];
                        result.push(fourData);
                    }
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找三张
         */
        public static findTreble(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            for (var i: number = 0; i < cardData.length; i++) {
                if (i + 2 < cardData.length)//如果剩余有4张
                {
                    if (this.getCardValue(cardData[i]) == this.getCardValue(cardData[i + 1])
                        && this.getCardValue(cardData[i + 1]) == this.getCardValue(cardData[i + 2])
                        && this.compare(cardData[i], minCard))//3张全部相等
                    {
                        var fourData: number[] = [cardData[i], cardData[i + 1], cardData[i + 2]];
                        result.push(fourData);
                    }
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找两张
         */
        public static findDouble(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            for (var i: number = 0; i < cardData.length; i++) {
                if (i + 1 < cardData.length)//如果剩余有4张
                {
                    if (this.getCardValue(cardData[i]) == this.getCardValue(cardData[i + 1]) && this.compare(cardData[i], minCard))//2张全部相等
                    {
                        var fourData: number[] = [cardData[i], cardData[i + 1]];
                        result.push(fourData);
                    }
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找三带两
         */
        public static findTrebleAndTwo(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var threeList: Array<number[]> = this.findTreble(cardData, minCard);//找出所有的三张
            if (threeList.length == 0) {
                return result;
            }
            for (var i: number = 0; i < threeList.length; i++) {
                var threeData: number[] = threeList[i];
                var newCardData: number[] = [];//踢除上面的三张
                for (var j: number = 0; j < cardData.length; j++) {
                    if (threeData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                var twoList: Array<number[]> = this.findDouble(newCardData);
                for (var a: number = 0; a < twoList.length; a++) {
                    result.push(threeData.concat(twoList[a]));
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找三带一
         */
        public static findTrebleAndOne(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var threeList: Array<number[]> = this.findTreble(cardData, minCard);//找出所有的三张
            if (threeList.length == 0) {
                return result;
            }
            for (var i: number = 0; i < threeList.length; i++) {
                var threeData: number[] = threeList[i];
                var newCardData: number[] = [];//踢除上面的三张
                for (var j: number = 0; j < cardData.length; j++) {
                    if (threeData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                var singleList: number[] = this.findSingle(newCardData);
                for (var a: number = 0; a < singleList.length; a++) {
                    result.push(threeData.concat(singleList[a]));
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找四带两单张
         */
        public static findFourfoldAndSingle(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var fourList: Array<number[]> = this.findBoom(cardData, minCard);//找出所有的四张
            if (fourList.length == 0) {
                return result;
            }
            for (var i: number = 0; i < fourList.length; i++) {
                var fourData: number[] = fourList[i];
                var newCardData: number[] = [];//踢除上面的四张
                for (var j: number = 0; j < cardData.length; j++) {
                    if (fourData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                var oneList: number[] = this.findSingle(newCardData);
                if (oneList.length >= 2) {//如果有超过2个单张
                    for (var a: number = 0; a < oneList.length; a++) {
                        if (a != oneList.length - 1) {
                            result.push(fourData.concat(oneList[a]).concat(oneList[a + 1]));
                        }
                    }
                    var twoList: Array<number[]> = this.findDouble(newCardData);
                    for (var a: number = 0; a < twoList.length; a++) {
                        result.push(fourData.concat(twoList[a]));
                    }
                }
                else {//否则就全部以单张的形式带入
                    oneList = newCardData.concat();
                    for (var a: number = 0; a < oneList.length; a++) {
                        if (a != oneList.length - 1) {
                            result.push(fourData.concat(oneList[a]).concat(oneList[a + 1]));
                        }
                    }
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找四带两对
         */
        public static findFourfoldAndDouble(cardData: number[], minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var fourList: Array<number[]> = this.findBoom(cardData, minCard);//找出所有的四张
            if (fourList.length == 0) {
                return result;
            }
            for (var i: number = 0; i < fourList.length; i++) {
                var fourData: number[] = fourList[i];
                var newCardData: number[] = [];//踢除上面的四张
                for (var j: number = 0; j < cardData.length; j++) {
                    if (fourData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                var twoList: Array<number[]> = this.findDouble(newCardData);
                if (twoList.length >= 2) {
                    for (var a: number = 0; a < twoList.length; a++) {
                        if (a != twoList.length - 1) {
                            result.push(fourData.concat(twoList[a]).concat(twoList[a + 1]));
                        }
                    }
                }
            }
            return this.removeSameValue(result);
        }
        /**
         * 查找王炸
         */
        public static findRocket(cardData: number[]): number[] {
            var result: number[] = [];
            if (cardData.indexOf(0x4f) != -1 && cardData.indexOf(0x4e) != -1) {
                result = [0x4f, 0x4e];
            }
            return result;
        }
        /**
         * 查找飞机-不带翅膀
         * @param cardData 自己的牌数据
         * @param length 一共有几个三张
         */
        public static findPlane(cardData: number[], length: number, minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            // minCard = minCard == 1 ? 14 - length : minCard - length;
            // minCard = minCard < 0 ? 0 : minCard;
            var threeList: Array<number[]> = this.findTreble(cardData, minCard);//找出所有的三张
            var newCardData: number[] = [];//变成单张，利用顺子函数去找
            for (var i = 0; i < threeList.length; i++) {
                newCardData.push(threeList[i][0]);
            }
            var lineList = this.findSingleLine(newCardData, length, 0x00, 2);
            for (var i = 0; i < lineList.length; i++) {
                var lineData: number[] = [];
                for (var k = 0; k < lineList[i].length; k++) {
                    for (var j = 0; j < threeList.length; j++) {
                        if (this.getCardValue(threeList[j][0]) == this.getCardValue(lineList[i][k])) {
                            lineData = lineData.concat(threeList[j])
                        }
                    }
                }
                result.push(lineData);
            }
            return result;
        }
        /**
         * 查找连对
         * @param cardData 自己的牌数据
         * @param length 一共有几个对子
         */
        public static findDoubleLine(cardData: number[], length: number = 3, minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            if (length < 3) {
                return result;
            }
            this.sortByCardData(cardData);
            var twoList: Array<number[]> = this.findDouble(cardData, minCard);//找出所有的两张
            var newCardData: number[] = [];//变成单张，利用顺子函数去找
            for (var i = 0; i < twoList.length; i++) {
                newCardData.push(twoList[i][0]);
            }
            var lineList = this.findSingleLine(newCardData, length, 0x00, 3);
            for (var i = 0; i < lineList.length; i++) {
                var lineData: number[] = [];
                for (var k = 0; k < lineList[i].length; k++) {
                    for (var j = 0; j < twoList.length; j++) {
                        if (this.getCardValue(twoList[j][0]) == this.getCardValue(lineList[i][k])) {
                            lineData = lineData.concat(twoList[j])
                        }
                    }
                }
                result.push(lineData);
            }
            return result;
        }
        /**
         * 飞机带单张
         * @param cardData 自己的牌数据
         * @param length 一共有几个三张
         */
        public static findPlaneAndSingle(cardData: number[], length: number, minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var planeList: Array<number[]> = this.findPlane(cardData, length, minCard);//找出所有的不带翅膀的飞机
            for (var i: number = 0; i < planeList.length; i++) {
                var planeData: number[] = planeList[i];
                var newCardData: number[] = [];//踢除上面的不带翅膀的飞机
                for (var j: number = 0; j < cardData.length; j++) {
                    if (planeData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                var singleList: number[] = this.findSingle(newCardData);
                if (singleList.length < length) {
                    singleList = newCardData;
                }
                if (singleList.length >= length) {
                    for (var a: number = 0; a < singleList.length; a++) {
                        var pushData = [];
                        for (var b = a; b < a + length; b++) {
                            if (b < singleList.length) {
                                pushData.push(singleList[b]);
                            }
                        }
                        if (pushData.length == length) {
                            result.push(planeData.concat(pushData));
                        }
                    }
                }
            }
            return result;
        }
        /**
         * 飞机带两对
         * @param cardData 自己的牌数据
         * @param length 一共有几个三张
         */
        public static findPlaneAndDouble(cardData: number[], length: number, minCard: number = 0x00): Array<number[]> {
            var result: Array<number[]> = [];
            this.sortByCardData(cardData);
            var planeList: Array<number[]> = this.findPlane(cardData, length, minCard);//找出所有的不带翅膀的飞机
            for (var i: number = 0; i < planeList.length; i++) {
                var planeData: number[] = planeList[i];
                var newCardData: number[] = [];//踢除上面的不带翅膀的飞机
                for (var j: number = 0; j < cardData.length; j++) {
                    if (planeData.indexOf(cardData[j]) == -1) {
                        newCardData.push(cardData[j]);
                    }
                }
                // var twoList: number[][] = this.findDouble(newCardData);
                // for (var a: number = 0; a < twoList.length; a++) {
                //     if (a != twoList.length - 1) {
                //         result.push(planeData.concat(twoList[a]).concat(twoList[a + 1]));
                //     }
                // }
                var twoList: number[][] = this.findDouble(newCardData);
                if (twoList.length >= length) {
                    for (var a: number = 0; a < twoList.length; a++) {
                        var pushData = [];
                        for (var b = a; b < a + length; b++) {
                            if (b < twoList.length) {
                                pushData.push(twoList[b]);
                            }
                        }
                        if (pushData.length == length) {
                            result.push(planeData.concat(pushData));
                        }
                    }
                }
            }
            return result;
        }
        /**
         * 获取牌型
         */
        public static getCardType(cardData: number[]): { type: CardType, value: number } {
            if (!cardData || cardData.length == 0) {
                return { type: CardType.Error, value: null };
            }
            if (cardData.length == 1) {//单张
                return { type: CardType.Single, value: cardData[0] };
            }
            if (cardData.length == 2) {
                if (this.getCardValue(cardData[0]) == this.getCardValue(cardData[1])) {//对子
                    return { type: CardType.Double, value: cardData[0] };
                }
                if (this.findRocket(cardData).length == 2) {//王炸
                    return { type: CardType.Rocket, value: cardData[0] };
                }
            }
            if (cardData.length == 3 && this.getCardValue(cardData[0]) == this.getCardValue(cardData[1]) && this.getCardValue(cardData[1]) == this.getCardValue(cardData[2])) {//三张
                return { type: CardType.Treble, value: cardData[0] };
            }
            if (cardData.length == 4) {//三带一或炸弹
                if (this.getCardValue(cardData[0]) == this.getCardValue(cardData[1]) &&
                    this.getCardValue(cardData[1]) == this.getCardValue(cardData[2]) &&
                    this.getCardValue(cardData[2]) == this.getCardValue(cardData[3])) {//炸弹
                    return { type: CardType.Boom, value: cardData[0] };
                }
                var trebleAndOneData = this.findTrebleAndOne(cardData);
                if (trebleAndOneData.length == 1) {//三带一
                    return { type: CardType.TrebleAndOne, value: trebleAndOneData[0][0] };
                }
            }
            if (cardData.length == 5) {//三带二或顺子
                var trebleAndTwoData = this.findTrebleAndTwo(cardData);
                if (trebleAndTwoData.length == 1) {//三带二
                    return { type: CardType.TrebleAndTwo, value: trebleAndTwoData[0][0] };
                }
                var singleLineData = this.findSingleLine(cardData, cardData.length);
                if (singleLineData.length == 1) {//顺子
                    return { type: CardType.SingleLine, value: singleLineData[0][0] };
                }
            }
            var fourfoldAndSingleData = this.findFourfoldAndSingle(cardData);
            if (fourfoldAndSingleData.length == 1 && cardData.length == 6) {//四带单张
                return { type: CardType.FourfoldAndSingle, value: fourfoldAndSingleData[0][0] };
            }
            var fourfoldAndDoubleData = this.findFourfoldAndDouble(cardData);
            if (fourfoldAndDoubleData.length == 1 && cardData.length == 8) {//四带两对
                return { type: CardType.FourfoldAndDouble, value: fourfoldAndDoubleData[0][0] };
            }
            var doubleLineData = this.findDoubleLine(cardData, cardData.length / 2);
            if (cardData.length % 2 == 0 && doubleLineData.length == 1 && doubleLineData[0].length == cardData.length) {//连对
                return { type: CardType.DoubleLine, value: doubleLineData[0][0] };
            }
            var singleLineData = this.findSingleLine(cardData, cardData.length);
            if (singleLineData.length == 1 && singleLineData[0].length == cardData.length) {//顺子
                return { type: CardType.SingleLine, value: singleLineData[0][0] };
            }
            var planeData = this.findPlane(cardData, cardData.length / 3);
            if (cardData.length % 3 == 0 && planeData.length == 1) {//飞机不带翅膀
                return { type: CardType.Plane, value: planeData[0][0] };
            }
            var planeAndSingleData = this.getPlaneAndSingleData(cardData);
            if (planeAndSingleData) {//飞机带单张翅膀
                return { type: CardType.PlaneAndSingle, value: planeAndSingleData.result[0] };
            }
            var planeAndDoubleData = this.getPlaneAndDoubleData(cardData);
            if (planeAndDoubleData) {//飞机带对子翅膀
                return { type: CardType.PlaneAndDouble, value: planeAndDoubleData.result[0] };
            }
            return { type: CardType.Error, value: null };
        }
        /**
         * 获取牌数据的值
         */
        public static getCardDataValue(cardData: number[]): number {
            if (cardData.length) {
                return this.getCardValue(cardData[0]);
            }
            else {
                return -1;
            }
        }
        /**
         * 根据长度智能获取用户牌
         */
        public static tipByLength(cardData: number[], length: number): number[][] {
            var result: number[][] = [];
            switch (length) {
                case 1://单张
                    var singleData = this.findSingle(cardData);
                    if (singleData.length) {
                        result.push([singleData[singleData.length - 1]]);
                        return result;
                    }
                    break;
                case 2://对子、王炸
                    var doubleData = this.findDouble(cardData);
                    if (doubleData.length) {
                        result.push(doubleData[doubleData.length - 1]);
                        return result;
                    }
                    var rocketData = this.findRocket(cardData);
                    if (rocketData.length) {
                        result.push(rocketData);
                        return result;
                    }
                    break;
                case 3:
                    var trebleData = this.findDouble(cardData);
                    if (trebleData.length) {
                        result.push(trebleData[trebleData.length - 1]);
                        return result;
                    }
                    break;
                case 4:
                    var boomData = this.findBoom(cardData);
                    if (boomData.length) {
                        result.push(boomData[boomData.length - 1]);
                        return result;
                    }
                    var trebleAndOneData = this.findTrebleAndOne(cardData);
                    if (trebleAndOneData.length) {//三带一
                        result.push(trebleAndOneData[trebleAndOneData.length - 1]);
                        return result;
                    }
                    break;
                case 5://顺子、三带二
                    var singleLineData = this.findSingleLine(cardData, length);
                    if (singleLineData.length) {
                        result.push(singleLineData[singleLineData.length - 1]);
                        return result;
                    }
                    var trebleAndTwoData = this.findTrebleAndTwo(cardData);
                    if (trebleAndTwoData.length) {
                        result.push(trebleAndTwoData[trebleAndTwoData.length - 1]);
                        return result;
                    }
                    break;
                default://顺子、连对、飞机、四带二
                    var singleLineData = this.findSingleLine(cardData, length);
                    if (singleLineData.length) {
                        result.push(singleLineData[singleLineData.length - 1]);
                        return result;
                    }
                    if (length % 2 == 0) {
                        var doubleLineData = this.findDoubleLine(cardData, length / 2);
                        if (doubleLineData.length) {
                            result.push(doubleLineData[doubleLineData.length - 1]);
                            return result;
                        }
                    }
                    if (length % 3 == 0) {
                        var planeData = this.findPlane(cardData, length / 3);
                        if (planeData.length) {
                            result.push(planeData[planeData.length - 1]);
                            return result;
                        }
                    }
                    var planeAndDouble = this.findPlaneAndDouble(cardData, length - 2);
                    if (planeAndDouble.length) {
                        result.push(planeAndDouble[planeAndDouble.length - 1]);
                        return result;
                    }
                    var planeAndSingle = this.findPlaneAndSingle(cardData, length - 2);
                    if (planeAndSingle.length) {
                        result.push(planeAndSingle[planeAndSingle.length - 1]);
                        return result;
                    }
                    var fourfoldAndDouble = this.findFourfoldAndDouble(cardData);
                    if (fourfoldAndDouble.length) {
                        result.push(fourfoldAndDouble[fourfoldAndDouble.length - 1]);
                        return result;
                    }
                    var fourfoldAndSingle = this.findFourfoldAndSingle(cardData);
                    if (fourfoldAndSingle.length) {
                        result.push(fourfoldAndSingle[fourfoldAndSingle.length - 1]);
                        return result;
                    }
                    break;
            }
            while (!result.length) {
                result = this.tipByLength(cardData, length - 1);
            }
            return result;
        }
        /**
         * 提示
         */
        public static tip(myCardData: number[], putCardData: number[]): number[][] {
            var putCardTypeData = this.getCardType(putCardData);
            var putCardType = putCardTypeData.type;
            // if (putCardType == CardType.Error) {
            //     return [];
            // }
            var result: number[][] = [];
            switch (putCardType) {
                case CardType.Error:
                    return this.tipByLength(myCardData, myCardData.length);
                case CardType.Single:
                    var singleData = this.findSingle(myCardData, putCardTypeData.value);
                    for (var i = 0; i < singleData.length; i++) {
                        result.push([singleData[i]]);
                    }
                    break;
                case CardType.Double:
                    var doubleData = this.findDouble(myCardData, putCardTypeData.value);
                    for (var i = 0; i < doubleData.length; i++) {
                        result.push(doubleData[i]);
                    }
                    break;
                case CardType.Treble:
                    var trebleData = this.findTreble(myCardData, putCardTypeData.value);
                    for (var i = 0; i < trebleData.length; i++) {
                        result.push(trebleData[i]);
                    }
                    break;
                case CardType.SingleLine:
                    var singleLineData = this.findSingleLine(myCardData, putCardData.length, putCardTypeData.value);
                    for (var i = 0; i < singleLineData.length; i++) {
                        result.push(singleLineData[i]);
                    }
                    break;
                case CardType.DoubleLine:
                    var doubleLineData = this.findDoubleLine(myCardData, putCardData.length / 2, putCardTypeData.value);
                    for (var i = 0; i < doubleLineData.length; i++) {
                        result.push(doubleLineData[i]);
                    }
                    break;
                case CardType.TrebleAndTwo:
                    var trebleAndTwoData = this.findTrebleAndTwo(myCardData, putCardTypeData.value);
                    for (var i = 0; i < trebleAndTwoData.length; i++) {
                        result.push(trebleAndTwoData[i]);
                    }
                    break;
                case CardType.TrebleAndOne:
                    var trebleAndOneData = this.findTrebleAndOne(myCardData, putCardTypeData.value);
                    for (var i = 0; i < trebleAndOneData.length; i++) {
                        result.push(trebleAndOneData[i]);
                    }
                    break;
                case CardType.FourfoldAndSingle:
                    var tourfoldAndSingleData = this.findFourfoldAndSingle(myCardData, putCardTypeData.value);
                    for (var i = 0; i < tourfoldAndSingleData.length; i++) {
                        result.push(tourfoldAndSingleData[i]);
                    }
                    break;
                case CardType.FourfoldAndDouble:
                    var fourfoldAndDoubleData = this.findFourfoldAndDouble(myCardData, putCardTypeData.value);
                    for (var i = 0; i < fourfoldAndDoubleData.length; i++) {
                        result.push(fourfoldAndDoubleData[i]);
                    }
                    break;
                case CardType.Plane:
                    var planeData = this.findPlane(myCardData, putCardData.length / 3, putCardTypeData.value);
                    for (var i = 0; i < planeData.length; i++) {
                        result.push(planeData[i]);
                    }
                    break;
                case CardType.PlaneAndSingle:
                    var putCardPlaneAndSingleData = this.getPlaneAndSingleData(putCardData);
                    var planeAndSingleData = this.findPlaneAndSingle(myCardData, putCardPlaneAndSingleData.threeLength, putCardTypeData.value);
                    for (var i = 0; i < planeAndSingleData.length; i++) {
                        result.push(planeAndSingleData[i]);
                    }
                    break;
                case CardType.PlaneAndDouble:
                    var putCardPlaneAndDoubleData = this.getPlaneAndDoubleData(putCardData);
                    var planeAndDoubleData = this.findPlaneAndDouble(myCardData, putCardPlaneAndDoubleData.threeLength, putCardTypeData.value);
                    for (var i = 0; i < planeAndDoubleData.length; i++) {
                        result.push(planeAndDoubleData[i]);
                    }
                    break;
                case CardType.Boom:
                    var boomData = this.findBoom(myCardData, putCardTypeData.value);
                    for (var i = 0; i < boomData.length; i++) {
                        result.push(boomData[i]);
                    }
                    break;
            }
            result.reverse();
            var boomResult = [];
            if (putCardType != CardType.Rocket && putCardType != CardType.Boom) {
                var boomData = this.findBoom(myCardData);
                for (var i = 0; i < boomData.length; i++) {
                    boomResult.push(boomData[i]);
                }
            }
            boomResult.reverse();
            var rocketData = this.findRocket(myCardData);
            if (rocketData.length) {
                boomResult.push(rocketData);
            }
            return result.concat(boomResult);
        }
        public static compare(left: number, right: number): boolean {
            var leftValue: number = this.getCardValue(left);
            var rightValue: number = this.getCardValue(right);
            leftValue = leftValue <= 2 && leftValue >= 1 ? 13 + leftValue / 10 : leftValue;
            rightValue = rightValue <= 2 && rightValue >= 1 ? 13 + rightValue / 10 : rightValue;
            return leftValue > rightValue;
        }
        /**
         * 获取飞机带单张的数据，如果不是此牌型则为空
         */
        public static getPlaneAndSingleData(cardData: number[]): { result: number[], threeLength: number } {
            for (var i = 0; i < cardData.length; i++) {
                var singleLength = i;
                var threeLength = -1;
                if ((cardData.length - singleLength) % 3 == 0) {
                    threeLength = (cardData.length - singleLength) / 3;
                }
                if (singleLength == threeLength) {
                    var planeAndSingle = this.findPlaneAndSingle(cardData, threeLength);
                    if (planeAndSingle.length == 1) {
                        return { result: planeAndSingle[0], threeLength: threeLength };
                    }
                }
            }
            return null;
        }
        /**
         * 获取飞机带两对的数据，如果不是此牌型则为空
         */
        public static getPlaneAndDoubleData(cardData: number[]): { result: number[], threeLength: number } {
            for (var i = 0; i < cardData.length; i++) {
                var doubleLength = i;
                var threeLength = -1;
                if ((cardData.length - doubleLength) % 3 == 0) {
                    threeLength = (cardData.length - doubleLength) / 3;
                }
                if (doubleLength / 2 == threeLength) {
                    var planeAndDouble = this.findPlaneAndDouble(cardData, threeLength);
                    if (planeAndDouble.length == 1) {
                        return { result: planeAndDouble[0], threeLength: threeLength };
                    }
                }
            }
            return null;
        }
        private static getValues(source: number[]): number[] {
            var result: number[] = [];
            for (var i = 0; i < source.length; i++) {
                result.push(this.getCardValue(source[i]));
            }
            return result;
        }
        private static removeSameValue2(source: number[]): number[] {
            var sourceValues: string[] = [];
            var result: number[] = [];
            for (var i = 0; i < source.length; i++) {
                var itemValues = this.getCardValue(source[i]);
                if (sourceValues.indexOf("[" + itemValues + "]") == -1) {
                    sourceValues.push("[" + itemValues + "]");
                    result.push(source[i]);
                }
            }
            return result;
        }
        private static removeSameValue(source: number[][]): number[][] {
            var sourceValues: string[] = [];
            var result: number[][] = [];
            for (var i = 0; i < source.length; i++) {
                var itemValues = this.getValues(source[i]);
                if (sourceValues.indexOf("[" + itemValues + "]") == -1) {
                    sourceValues.push("[" + itemValues + "]");
                    result.push(source[i]);
                }
            }
            return result;
        }
    }
}